// debugstream.cpp
//
// General-purpose debug stream, like std::cout


#include "debugStream.h"
#include <time.h>

namespace simple{
    //
    // DebugSink
    //
    DebugSink::DebugSink () : _enableHeader(false) {}

    std::string DebugSink::standardHeader ()
    {
        std::string header;

        // Fetch the current time
        time_t now = time(0);
        header += ctime (&now);
        header.erase (header.length()-1, 1); // Remove newline written
        header += ": ";

        return header;
    }


    // 
    // DebugSinkNull
    //
    DebugSinkNull DebugSinkNull::sOnly = DebugSinkNull ();

    DebugSinkNull::DebugSinkNull () {}


    //
    // DebugSinkConsole
    //
    DebugSinkConsole DebugSinkConsole::sOnly = DebugSinkConsole ();

    DebugSinkConsole::DebugSinkConsole  () {}
    DebugSinkConsole::~DebugSinkConsole () { flush();}


    void DebugSinkConsole::write (const std::string& str)
    {
        _buffer += str;
        flush ();
    }

    void DebugSinkConsole::write (int c)
    {
        _buffer += (char)c;
        if (c == '\n')
            flush ();
    }

    void DebugSinkConsole::display (const std::string& str)
    {
        std::cout << str;
    }

    void DebugSinkConsole::flush ()
    {
        if (_buffer.empty())
            return;

        if (_enableHeader)
            _buffer = header() + _buffer;

        // Add a trailing newline if we don't have one
        // (we need this when we shut down)
        if (_buffer[_buffer.length()-1] != '\n')
            _buffer += '\n';

        display (_buffer);
        _buffer.clear ();
    }


    //
    // DebugSinkFile
    //
    DebugSinkFile DebugSinkFile::sOnly = DebugSinkFile ();

    DebugSinkFile::DebugSinkFile    () {}
    DebugSinkFile::~DebugSinkFile () { flush();}

    void DebugSinkFile::setFile (const std::string& file)
    {
        flush(); 
        _file = file;
    }

    void DebugSinkFile::display (const std::string& str)
    {
        if (_file.empty())
            return;

        // Open the file in append mode. The dtor will close
        // the file for us.
        std::ofstream output (_file.c_str(), std::ios_base::app);
        if (!output)
            return;    // The file could not be opened. Exit

        output << str;
    }



    // 
    // DebugStringBuf
    //

    DebugStringBuf<char> debugstream;

    std::ostream cdebug (&debugstream);

}